﻿#include <utility>

//
// Created by hujin on 2020/10/6.
//

#ifndef C_MIPS_CMPLR_AST_DEF_H
#define C_MIPS_CMPLR_AST_DEF_H

#include "ast.h"
#include "../symbolTable.h"
class CnstListNode : public ASTNode {
	std::vector<CnstDefNode*> list;
public:
	explicit CnstListNode(std::vector<CnstDefNode*>& list) : list(std::move(list)) {}
};

class CnstDefNode : public ASTNode {
	bool isInt;
	std::vector<std::pair<std::string, int>> val;
public:
	explicit CnstDefNode(bool isInt, std::vector<std::pair<std::string, int>>& val) : isInt(isInt), val(std::move(val)) {}

	void addToTable(SymbolTable* table) override;
};

class IntNode : public ASTNode {
public:
	int dat;
	explicit IntNode(int val) {
		dat = val;
	};
};


class CnstNode : public ASTNode {
public:
	bool isInt;
	int val;
	explicit CnstNode(char c) : val(c), isInt(false) {}
	explicit CnstNode(int intNode) : val(intNode), isInt(true) {}
};


class VarListNode : public ASTNode {
	std::vector<VarDefNode*> list;
public:
	explicit VarListNode(std::vector<VarDefNode*>& list) : list(std::move(list)) {}
    void genCode(Synthesizer *out, MemoryAllocator *allocator, bool isGlobal);
};

struct Var_data {
	std::string name;
	int size[2] = {};
	int dimension;
	Identifier_Data dat = {};
	union {
		int initialData = 0;
		std::vector<int> initialData1;
		std::vector<std::vector<int>> initialData2;
	};

	Var_data(std::string& name, int dimension, const int s[2]) : name(std::move(name)), dimension(dimension) { size[0] = s[0]; size[1] = s[1]; };
	Var_data(std::string& name, int initialData) : name(std::move(name)), dimension(0), initialData(initialData) {}
	Var_data(std::string& name, const int size[2], std::vector<int>& initialData) : name(std::move(name)), dimension(1), initialData1(std::move(initialData)) {
		this->size[0] = size[0];
	}
	Var_data(std::string& name, const int size[2], std::vector<std::vector<int>>& initialData) : name(std::move(name)), dimension(2), initialData2(std::move(initialData)) {
		this->size[0] = size[0]; this->size[1] = size[1];
	}
	~Var_data();
};

class VarDefNode : public ASTNode {
protected:
	bool isInt;
	bool init = false;
	std::vector<Var_data*> data;
public:
	VarDefNode(bool isInt, std::vector<Var_data*>& data) : isInt(isInt), data(std::move(data)) {}
	void addToTable(SymbolTable* table) override;
	~VarDefNode() { for (auto x : data) { delete x; } }

    void genCode(Synthesizer *out, MemoryAllocator *allocator, bool isGlobal);
};

class VarDefInitNode : public VarDefNode {
public:
	VarDefInitNode(bool isInt, std::vector<Var_data*>& data) : VarDefNode(isInt, data) {
	    init = true;
	};
};


#endif //C_MIPS_CMPLR_AST_DEF_H
